#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "../umlcore/BaseElement.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Element;
class UMLStyle;

/// <summary>
/// UMLDiagramElement
/// The most general class for UML diagram interchange.
/// </summary>
class UMLMODEL_EXPORT UMLDiagramElement : public BaseElement {

public: // Constructors and destructors
    explicit UMLDiagramElement(const QString& umlType="uml::UMLDiagramElement");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Properties
    /// <summary>
    /// modelElements getter
    /// Restricts UMLDiagramElements to show UML Elements, rather than other language
    /// elements. 
    /// </summary>
    vector<shared_ptr<Element>>& modelElements();

    /// <summary>
    /// sharedStyle getter
    /// Restricts shared styles to UMLStyles.
    /// </summary>
    shared_ptr<UMLStyle> sharedStyle() const;

    /// <summary>
    /// sharedStyle setter
    /// Restricts shared styles to UMLStyles.
    /// </summary>
    void setSharedStyle(shared_ptr<UMLStyle> value);

    /// <summary>
    /// localStyle getter
    /// Restricts owned styles to UMLStyles.
    /// </summary>
    shared_ptr<UMLStyle> localStyle() const;

    /// <summary>
    /// localStyle setter
    /// Restricts owned styles to UMLStyles.
    /// </summary>
    void setLocalStyle(shared_ptr<UMLStyle> value);

    /// <summary>
    /// owningElement getter
    /// Restricts UMLDiagramElements to be owned by only UMLDiagramElements.
    /// </summary>
    shared_ptr<UMLDiagramElement> owningElement() const;

    /// <summary>
    /// owningElement setter
    /// Restricts UMLDiagramElements to be owned by only UMLDiagramElements.
    /// </summary>
    void setOwningElement(shared_ptr<UMLDiagramElement> value);

    /// <summary>
    /// isIcon getter
    /// For modelElements that have an option to be shown with shapes other than
    /// rectangles, such as Actors, or with other identifying shapes inside them, such
    /// as arrows distinguishing InputPins and OutputPins, or edges that have an option
    /// to be shown with lines other than solid with open arrow heads, such as
    /// Realization.  A value of true for isIcon indicates the alternative notation
    /// shall be shown.
    /// </summary>
    bool isIcon() const;

    /// <summary>
    /// isIcon setter
    /// For modelElements that have an option to be shown with shapes other than
    /// rectangles, such as Actors, or with other identifying shapes inside them, such
    /// as arrows distinguishing InputPins and OutputPins, or edges that have an option
    /// to be shown with lines other than solid with open arrow heads, such as
    /// Realization.  A value of true for isIcon indicates the alternative notation
    /// shall be shown.
    /// </summary>
    void setIsIcon(bool value);

    /// <summary>
    /// ownedElements getter
    /// Restricts UMLDiagramElements to own only UMLDiagramElements.
    /// </summary>
    vector<shared_ptr<UMLDiagramElement>>& ownedElements();

private: // Fields
    /// <summary>
    /// modelElements
    /// Restricts UMLDiagramElements to show UML Elements, rather than other language
    /// elements. 
    /// </summary>
    vector<shared_ptr<Element>> modelElements_;

    /// <summary>
    /// sharedStyle
    /// Restricts shared styles to UMLStyles.
    /// </summary>
    shared_ptr<UMLStyle> sharedStyle_;

    /// <summary>
    /// localStyle
    /// Restricts owned styles to UMLStyles.
    /// </summary>
    shared_ptr<UMLStyle> localStyle_;

    /// <summary>
    /// owningElement
    /// Restricts UMLDiagramElements to be owned by only UMLDiagramElements.
    /// </summary>
    shared_ptr<UMLDiagramElement> owningElement_;

    /// <summary>
    /// isIcon
    /// For modelElements that have an option to be shown with shapes other than
    /// rectangles, such as Actors, or with other identifying shapes inside them, such
    /// as arrows distinguishing InputPins and OutputPins, or edges that have an option
    /// to be shown with lines other than solid with open arrow heads, such as
    /// Realization.  A value of true for isIcon indicates the alternative notation
    /// shall be shown.
    /// </summary>
    const static bool isIcon_default_;
    bool isIcon_= isIcon_default_;

    /// <summary>
    /// ownedElements
    /// Restricts UMLDiagramElements to own only UMLDiagramElements.
    /// </summary>
    vector<shared_ptr<UMLDiagramElement>> ownedElements_;

};

} // namespace uml
